The Azure SQL Edge demo is based on a Contoso Renewable Energy, a wind turbine farm that leverages Azure SQL Edge for data processing onboard the generator.
The demo will walk you through resolving an alert being raised due to wind turbulence being detected at the device. You will train a model and deploy it to SQL DB Edge that will correct the detected wind wake and ultimately optimize power output.
We will also look at some of the security features available with Azure SQL Edge.
The data stored in the database table represents the following:
- RecordId:Unique identifier for the entry.
- TurbineId:Unique identifier for the turbine in scope.
- GearboxOilLevel:Oil level recorded for the turbine gear box at the time of the reading.
- GearboxOilTemp:Oil temperature recorded for the turbine gear box at the time of the reading.
- GeneratorActivePower:Active Power recorded by the turbine generator.
- GeneratorSpeed:Speed recorded by the turbine generator.
- GeneratorTemp:Temperature recorded by the turbine generator.
- GeneratorTorque:Torque recorded by the turbine generator.
- GridFrequency:Frequency recorded in the grid for the specific wind turbine.
- GridVoltage:Voltage recorded in the grid for the specific wind turbine.
- HydraulicOilPressure:Current pressure of the hydraulic oil for the wind turbine.
- NacelleAngle:Angle of the nacelle at the time of the reading (the housing that contains all the generating components).
- PitchAngle:Pitch angle of the blades against the oncoming air stream to obtain the optimal amount of energy.
- Vibration:Vibration of the wind turbine at the time of the reading.
- WindSpeedAverage:Average wind speed calculated from the last X records.
- Precipitation:Flag to represent if rain was present at the time of the reading.
- WindTempAverage:Average wind temperature calculated from the last X records.
- OverallWindDirection:Overall wind direction recorded at the time of the reading.
- TurbineWindDirection:Turbine wind direction recorded at the time of the reading.
- TurbineSpeedAverage:Average turbine speed calculated from the last X records.
- WindSpeedStdDev:Standard Deviation of the last X WindSpeedAverage records.
- TurbineSpeedStdDev:Standard Deviation of the last X TurbineSpeedAverage records.
The above dataset definition contains trends that will enable us to detect the existence of wake in a wind turbine. There are two main conditions that influence the presence of wind wake:
- Overall wind farm and turbine wind direction are both between 40° - 45° degrees.
- TurbineSpeedStdDev and WindSpeedStdDev have been too far apart for greater than a minute.
The wind turbine will experience wake when the turbine wind direction is between 40° - 45° degrees and the values of TurbineSpeedStdDev and WindSpeedStdDev are not similar. For example:
- Wake Present:
- TurbineWindDirection = 43.5°
- TurbineSpeedStdDev = 8.231
- WindSpeedStdDev = 0.23
- Wake Not Present:
- TurbineWindDirection = 23.5°
- TurbineSpeedStdDev = 0.921
- WindSpeedStdDev = 0.213
An Azure Resource Manager (ARM) template will be used to deploy all the required resources in the solution. Click on the link below to start the deployment.
TODO ^^ Need to update the ARM location
Follow the steps to deploy the required Azure resources:
BASICS
- Subscription: Select the Subscription.
- Resource group: Click on 'Create new' and provide a unique name for the Resource Group
- Location: Select the Region where to deploy the resources. Keep in mind that all resources will be deployed to this region so make sure it supports all of the required services. The template has been confirmed to work in West US 2.
- Read and accept the
TERMS AND CONDITIONS
by checking the box. - Click the
Purchase
button and wait for the deployment to finish.
Some resources require some extra configuration.
The Edge Module will require access the DACPAC package in order to setup the database.
- In the Azure portal select the Resource Group you created earlier.
- Select the Storage account resource from the list.
- Click the Containers option in the left menu under Blob service.
- Click the dacpac container.
- Click the Upload button.
- Click the Select a file input and select the file under the project folder:
sql/turbine-sensor-db-dacpac.zip
. - Click the Upload button.
- Once the file is uploaded, click on it.
- Click Generate SAS tab.
- Update the Expiry year to 2050.
- Click Generate SAS token and URL
- Copy the value in Blob SAS URL and save it for later in the setup.
As security settings were deployed as part of the DACPAC package, below is a review of the security setup within the database.
Create users without a login for simpler testing:
/* Create users using the logins created */CREATEUSEROperatorUser WITHOUT LOGIN; CREATEUSERDataScientistUser WITHOUT LOGIN; CREATEUSERSecurityUser WITHOUT LOGIN; CREATEUSERTurbineUser WITHOUT LOGIN;
Assigned permissions for each user:
/* Grant permissions to users */GRANTSELECTON RealtimeSensorRecord TO OperatorUser; GRANTSELECTON RealtimeSensorRecord TO DataScientistUser; GRANTSELECTON RealtimeSensorRecord TO SecurityUser; GRANTSELECT, INSERT ON RealtimeSensorRecord TO TurbineUser;
Note: All users can SELECT, however the TurbineUser can also INSERT to the table.
For privacy reasons, mask the last 4 digits of the SensorId for the Data Scientist user:
/*Mask the last four digits of the serial number (Sensor ID) for the Data Scientist User*/ALTERTABLE RealtimeSensorRecord ALTER COLUMN SensorId varchar(50) MASKED WITH (FUNCTION ='partial(34,"XXXX",0)'); DENY UNMASK TO DataScientistUser; GO
Add a policy using a filter predicate and a function to manage access to data events:
We updated the SensorType column as it is required in our function then created a new schema to store it.
/*** Operator: Can see all events* Data Scientist: Can see everything BUT Hatch Sensor events* Security: Can ONLY see Hatch Sensor events*/ALTERTABLE RealtimeSensorRecord ALTER COLUMN SensorType sysname GO CREATESCHEMASecurity; GO
Add the function that will ensure each query is authorized based on Sensor Type/User.
/*** Operator: Can see all events* Data Scientist: Can see everything BUT Hatch Sensor events* Security: Can ONLY see Hatch Sensor events*/CREATEFUNCTIONSecurity.fn_securitypredicate(@SensorType AS sysname) RETURNS TABLE WITH SCHEMABINDING AS RETURN SELECT1AS fn_securitypredicate_result WHERE USER_NAME() ='OperatorUser'OR USER_NAME() ='dbo'OR (USER_NAME() ='DataScientistUser'AND @SensorType <>'HatchSensor') OR (USER_NAME() ='SecurityUser'AND @SensorType ='HatchSensor');
Add a filter to to use the function.
CREATE SECURITY POLICY SensorsDataFilter ADD FILTER PREDICATE Security.fn_securitypredicate(SensorType) ONdbo.RealtimeSensorRecord WITH (STATE =ON);
In this section, we will setup our notebook with the required files for the generation of the wind adapt model.
- In the Azure portal select the Resource Group you created earlier.
- Select the Storage account resource.
- Click the Containers option in the left menu under Blob service.
- Click the azureml-blobstore-GUID container.
- Click the Upload button in the top.
- Click the Select a file input and select the
ml\data\TrainingDataset.parquet
from your repo. - Click the Upload button and wait for the upload to finish.
Select Azure Active Directory option from the main navigation in the Azure Portal:
Copy the Tenant Id value from the overview as you will need this value later.
Go back to the Resource Group you created earlier.
Select the Machine Learning resource.
Take note of the following values to be used later in the deployment
Click the Launch now button to open the Machine Learning workspace.
Click the Notebooks option in the left menu under Author.
Click the Create new folder button at the top of the navigation panel.
Enter the name
scripts
for as the folder name and click the Create button.Click the Upload files button at the top of the navigation panel.
Select the 2 files inside the
ml\scripts
folder:- ml\scripts\train.py
- ml\scripts\utils.py
Select the newly created
scripts
folder from the target directory list.Click the Upload button and wait for the upload to finish.
Click the Upload files button again.
Select the following 2 files inside the
ml
folder:- ml\utils.py
- ml\wind-turbine-scikit.ipynb
Note: The
utils.py
is a different file from the previous step.Select your username folder from the target directory list.
Click the Upload button.
We need configure values within the notebook before being able to execute it:
Click the
wind-turbine-scikit.ipynb
in the My files navigation:Click the New Compute button.
Enter the name
compute-{your-initials}
.Select CPU (Central Processing Unit) from the Virtual machine type dropdown.
Select the virtual machine size Standard_D12_v2.
Click the Create button and wait for the compute to be created.
Note: This process can take several minutes; wait until status of compute is
Running
.Click the Edit dropdown and select the Edit in Jupyter option.
Note: If required, login with your Azure credentials.
Replace the values within the Setup Azure ML cell with the values you obtained in the Notebook files upload section:
interactive_auth = InteractiveLoginAuthentication(tenant_id="<tenant_id>") # Get instance of the Workspace and write it to config file ws = Workspace( subscription_id = '<subscription_id>', resource_group = '<resource_group>', workspace_name = '<workspace_name>', auth = interactive_auth)
Click File > Save and Checkpoint from the menu.
Select the Install requirements cell and click Run from the menu, wait for the script to execute before continuing.
Select the Setup Azure ML cell and click Run from the menu.
IMPORTANT: Observe the output to authenticate via the URL provided (https://microsoft.com/devicelogin).
From here, Run the remaining cells sequentially until you have executed the notebook.
IMPORTANT: Remember to wait for each cell to execute before continuing.
Go back to the azure resource group and click the Storage Account resource.
Click the Containers option in the left menu.
Click the container in the list with a name like:
azureml-blobstore-{guid}
.A new file with the name
windturbinewake.model.onnx
will be in the container.Click the
windturbinewake.model.onnx
fileClick the Generate SAS tab option.
Change the Expiry Year to 2050.
Click the Generate SAS token and URL button and wait for the SAS to be generated.
Copy the Blob SAS URL value for later in the demo usage section.
IMPORTANT: As this process does take some time, once you have saved your model to blob storage, you will not be required to execute this every time you run through the demo. Showing the notebook flow may be adequate for demo purposes. You will just need the blob SAS for the SQL DB Edge Demo Usage section later in the document.
In this section, we will set up an Edge device within our IoT Hub instance.
- In the Azure portal select the Resource Group you created earlier.
- Select the IoT Hub resource.
- Click on IoT Edge from the left navigation.
- Click + Add an IoT Edge Device.
- Enter a Device ID and leave all other fields as default.
- Click Save.
- Once the device has been created, select the device and copy the Primary Connection String for later in this setup.
Click on the link below to start the deploy to Azure:
On the newly launched window, fill in the available form fields:
- Subscription: Your subscription.
- Resource group: Select the resource group you created earlier.
- DNS Label Prefix: Your initials and birth year.
- Admin Username: Enter
microsoft
as default. - Device Connection String: The device connection string that you got from previous section.
- VM Size: The size of the virtual machine to be deployed.
- Ubuntu OS Version: The version of the Ubuntu OS to be installed on the base virtual machine.
- Location: The geographic region to deploy the virtual machine into, this value defaults to the location of the selected Resource Group.
- Authentication Type: Choose the password option.
- Admin Password or Key: Enter
M1cr0s0ft2020
.
Accept the Terms and Conditions.
Select Purchase to begin the deployment.
Once the deployment is complete, go back to the Resource Group you created earlier.
Select the Virtual Machine resource.
Note: Take note of the machine name, this should be in the format vm-0000000000000. Also, take note of the associated DNS Name, which should be in the format
<dnsLabelPrefix>.<location>.cloudapp.azure.com
. The DNS Name can be obtained from the Overview section of the newly deployed virtual machine within the Azure portal.If you want to SSH into this VM after setup, use the associated DNS Name with the command:
ssh <adminUsername>@<DNS_Name>
. You can use the password you created in the previous step.IMPORTANT: There is an optional section at the end of this document showing some example commands.
- Install Visual Studio Code (VS Code).
- Install Docker Community Edition (CE). Don't sign in to Docker Desktop after Docker CE is installed.
- Install the following extensions for VS Code:
- Azure Machine Learning (Azure Account will be automatically installed)
- Azure IoT Hub Toolkit
- Azure IoT Edge
- Docker Extension
- Restart VS Code.
- Select [View > Command Palette…] to open the command palette box, then enter [Python: Select Interpreter] command in the command palette box to select your Python interpreter.
- Enter [Azure: Sign In] command in the command palette box to sign in Azure account and select your subscription.
Launch Visual Studio Code, and select File > Open Workspace... command to open the
edge\sensor-solution.code-workspace
.Update the .env file with the values for your container registry.
In the Azure portal select the Resource Group you created earlier.
Select the Container Registry resource.
Select Access Keys from the left navigation.
Update the following in
edge/SensorSolution/.env
with the following values from Access Keys within the Container Registry:CONTAINER_REGISTRY_NAME=
<Login Server>
(Ensure this is the login server and NOT the Registry Name)CONTAINER_REGISTRY_USER_NAME=
<Username>
CONTAINER_REGISTRY_PASSWORD=
<Password>
SQL_PACKAGE=
<SQL Package Blob URL>
(the one you obtained earlier in the setup)Save the file.
Sign in to your Azure Container Registry by entering the following command in the Visual Studio Code integrated terminal (replace <REGISTRY_USER_NAME>, <REGISTRY_PASSWORD>, and <REGISTRY_NAME> with your container registry values set in the .env file IN THE PREVIOUS STEP).
docker login -u <CONTAINER_REGISTRY_USER_NAME> -p <CONTAINER_REGISTRY_PASSWORD> <CONTAINER_REGISTRY_NAME>
IMPORTANT: Ensure you have
amd64
selected as the architecture in the bottom navigation bar of VS Code.Right-click on
edge/SensorSolution/deployment.debug.template.json
and select the Build and Push IoT Edge Solution command to generate a newdeployment.debug.amd64.json
file in the config folder, build a module image, and push the image to the specified ACR repository.IMPORTANT: If you have amended code in your module, you will need to increment the version number in
module.json
so the new version will get deployed to the device in the next steps.Note: Some red warnings "/usr/bin/find: '/proc/XXX': No such file or directory" and "debconf: delaying package configuration, since apt-utils is not installed" displayed during the building process can be ignored.
Ensure you have the correct Iot Hub selected in VS Code.
- In the Azure IoT Hub extension, click Select IoT Hub from the hamburger menu. (Alternatively, select
Azure IoT Hub: Select IoT Hub
from the Command Palette) - Select your Subscription.
- Select the IoT Hub you created earlier in the setup.
- In the Azure IoT Hub extension, click Select IoT Hub from the hamburger menu. (Alternatively, select
Right-click
config\deployment.debug.amd64.json
and select Create Deployment for a Single Device.Select the device you created earlier.
Wait for deployment to be completed.
Follow the next steps to setup the required module twin connection string property.
- In the Azure portal select the Resource Group you created earlier.
- Select the IoT Hub resource.
- Click the IoT Edge option in the left menu under Automatic Device Management.
- Click the device you created earlier.
- Click the SensorModule from the modules list.
- Copy the Connection string (primary key) value and save for the next step.
- Go back to your Resource Group.
- Select the App Service resource.
- Click the Configuration option in the left menu.
- Under the Application settings find the
IoTHub:ModuleConnectionString
and click it. - Paste the module connection string that you got before to the
value
input field. - Click the OK button.
- Click the Save button on the top to apply the change.
Open the Web App.
- In the Azure portal select the Resource Group you created earlier.
- Select the App Service resource.
- Click Browse to go the application on a desktop machine.
Investigate Turbine Issue
- Click view on the alert. A query is ran against the SQL DB Edge instance.
- Notice the Operator can't see the Security Alert due to as the permissions we set earlier.
- You can notice a drop in the Power Generated chart.
- Click the Environmental button.
- You can notice the Wind Speed and Direction at the turbine is a lot more turbulent than the rest of the Wind Farm. This could indicate wind wake.
Now we need to run our notebook in order to generate the Onnx model that we will use to resolve the alert.
Important: As mentioned earlier in the document, you can choose to run through executing the notebook cells in the
Notebook Setup
section again to obtain the model. Or you can use your Blob URL you created during the initial setup.
Now we have our wind adapt model, lets update the module to correct the turbine.
- Go back to the azure resource group and click the IoT Hub resource.
- Click the Iot Edge option in the left menu.
- Click the created device from previous steps.
- Click the SensorModule from the modules list.
- Click the Module Identity Twin option in the top menu.
- Find the
properties
section in the json. - Find the
desired
section in the json. - Find the
OnnxModelUrl
property and update the value with the model Blob URL from the previous section. - Click the Save button.
- Go back to the Web App.
- You will notice a notification indicating the alert has been resolved.
- Click on the Resfresh button.
- Notice the turbine Wind Speed and Direction has stabilized.
- If you go back to the dashboard view. You will notice Unit 34 no longer has an alert.
This steps allows you to restart the demo.
- Go back to the azure resource group and click the IoT Hub resource.
- Click the Iot Edge option in the left menu.
- Click the created device from previous steps.
- Click the SensorModule from the modules list.
- Click the Module Identity Twin option in the top menu.
- Find the
properties
section in the json. - Find the
desired
section in the json. - Find the
OnnxModelUrl
property set the value as empty.
Note: Since the
Alert
property value was already instart
we don't need to updated it but the module will set the reported property with this value.
- Click the Save button.
- Go back to the Web App and refresh.
- After a short time the alert will appear again.
This section describe steps that allow us to see extra features of the resources as a reference only.
Here we will see how to run commands into to the device virtual machine from the terminal using SSH connection.
In the Azure portal select the Resource Group you created earlier.
Select the Virtual machine resource.
Copy the DNS name to use it for the connection.
In a terminal run the following command replacing the DNS name:
ssh microsoft@<DNS_Name>
Note: The above command is assuming that you use the default Admin username when deploying the VM.
Enter the password to connect.
Note: Default password is:
M1cr0s0ft2020
Run the following command to see the list of modules running:
sudo iotedge list
Note: You can should be able to see the
AzureSQLDatabaseEdge
andSensorModule
we deployed earlier.Run the following command to see the logs of the Sensor Module:
sudo iotedge logs SensorModule
- Following we will connect with the edge sql server to run a simple query by doing:
- Get the list of containers running with docker:
sudo docker container list
. - Get the container ID of the
AzureSQLDatabaseEdge
docker image running. - Connect to the container using the id that you got and the command:
sudo docker exec -it CONTAINERID /bin/sh
. - Connect to the container using:
/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Microsoft2020$'
. - Connect to the database using:
USE [turbine-sensor-db]
and thengo
. - Query the number of records in the table using:
select count(*) from RealtimeSensorRecord
andgo
.
- Get the list of containers running with docker:
- Following we will connect with the edge sql server to run a simple query by doing:
We've seen issues with different subscription types: MSDN, AIRS, etc... not being able to deploy certain resources to certain regions. We've found that deploying to West US 2 works consistently. If you have a deployment error, try deploying to West US 2. The resources inherit their deployment region from the Resource Group location.